package com.boatAnchorAssistant.service.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boatAnchorAssistant.pojo.entity.DataDictionary;
import com.boatAnchorAssistant.pojo.entity.DataDictionaryType;
import com.boatAnchorAssistant.pojo.entity.User;
import com.boatAnchorAssistant.pojo.exception.dataDictionaryType.DataDictionaryTypeErrorException;
import com.boatAnchorAssistant.pojo.param.dataDictionary.*;
import com.boatAnchorAssistant.pojo.vo.dataDictionary.*;
import com.boatAnchorAssistant.pojo.dto.dataDictionary.*;
import com.boatAnchorAssistant.service.repository.in.DataDictionaryRepository;
import com.boatAnchorAssistant.service.repository.in.DataDictionaryTypeRepository;
import com.boatAnchorAssistant.service.repository.in.UserRepository;
import com.boatAnchorAssistant.service.service.in.DataDictionaryService;
import nirvana.core.domains.vo.PageResult;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 【描 述】：数据字典服务
 * 【环 境】：J2SE 17
 * 【详 细】：
 *
 */
@Service
public class DataDictionaryServiceImpl implements DataDictionaryService {

    private final DataDictionaryRepository dataDictionaryRepository;

    private final UserRepository userRepository;

    private final DataDictionaryTypeRepository dataDictionaryTypeRepository;

    private final StringRedisTemplate stringRedisTemplate;

    public DataDictionaryServiceImpl(DataDictionaryRepository dataDictionaryRepository, UserRepository userRepository, DataDictionaryTypeRepository dataDictionaryTypeRepository, StringRedisTemplate stringRedisTemplate) {
        this.dataDictionaryRepository = dataDictionaryRepository;
        this.userRepository = userRepository;
        this.dataDictionaryTypeRepository = dataDictionaryTypeRepository;
        this.stringRedisTemplate = stringRedisTemplate;
    }


    /**
     * 创建数据字典
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createDataDictionary(CreateDataDictionaryParam param) {
        Long type = param.getType();
        dataDictionaryTypeRepository.getByIdCheck(type);


        DataDictionary t = new DataDictionary();
        t.setType(type);
        Integer number = dataDictionaryRepository.getListByEntity(t).size() + 1;

        //分配编号
        HashOperations<String, String, String> hash = stringRedisTemplate.opsForHash();
        String key = "DataDictionary_" + param.getType();
        String code = number.toString();


        while (!(hash.putIfAbsent(key, code, code) && !dataDictionaryRepository.hasCode(code, type))) {
            number++;
            code = number.toString();
        }
        DataDictionary dataDictionary = new DataDictionary();
        BeanUtils.copyProperties(param, dataDictionary);
        dataDictionary.setCode(code);
        Long id = IdGenerator.SNOW.generate();
        dataDictionary.setId(id);


        Integer displayOrder = param.getDisplayOrder();

        DataDictionary po = new DataDictionary();
        po.setType(type);
        po.setDisplayOrder(displayOrder);
        DataDictionary byPo = dataDictionaryRepository.getByEntity(po);

        if (byPo != null) {
            //把原本这个排序和后续字段往后排一位
            List<DataDictionary> dataDictionaryList = dataDictionaryRepository.getAfterListByOrder(type, displayOrder);

            for (DataDictionary dictionary : dataDictionaryList) {
                Integer order = dictionary.getDisplayOrder();
                dictionary.setDisplayOrder(order + 1);
            }
            dataDictionaryRepository.saveOrUpdateBatch(dataDictionaryList);
        } else {
            //校验这个排序有没有超过最后的排序+1位
            DataDictionary lastDisplay = dataDictionaryRepository.getLastDisplay(type);
            if (lastDisplay == null) {
                dataDictionary.setDisplayOrder(1);
            } else {
                Integer lastDisplayOrder = lastDisplay.getDisplayOrder();
                int maxOrder = lastDisplayOrder + 1;
                if (displayOrder > maxOrder) {
                    dataDictionary.setDisplayOrder(maxOrder);
                }
            }
        }
        dataDictionaryRepository.create(dataDictionary);
    }

    /**
     * 修改数据字典
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editDataDictionary(EditDataDictionaryParam param) {
        Long id = param.getId();
        DataDictionary dataDictionary = dataDictionaryRepository.getByIdCheck(id);

        Long type = param.getType();
        dataDictionaryTypeRepository.getByIdCheck(type);
        BeanUtils.copyProperties(param, dataDictionary);

        Integer displayOrder = param.getDisplayOrder();


        //重置排名
        DataDictionary t = new DataDictionary();
        t.setType(param.getType());
        List<DataDictionary> dataDictionaryList = dataDictionaryRepository.getListByEntity(t);
        for (DataDictionary dictionary : dataDictionaryList) {
            Long dictionaryId = dictionary.getId();
            if (dictionaryId.equals(id)) {
                //计算调整后的排序，不能超过总数
                int size = dataDictionaryList.size();
                if (displayOrder > size) {
                    displayOrder = size;
                }
                dictionary.setDisplayOrder(displayOrder);
                dataDictionary.setDisplayOrder(displayOrder);
            } else {
                Integer order = dictionary.getDisplayOrder();
                if (order >= displayOrder) {
                    dictionary.setDisplayOrder(order + 1);
                }
            }
        }
        dataDictionaryList = dataDictionaryList.stream()
                .sorted(Comparator.comparingInt(DataDictionary::getDisplayOrder))
                .collect(Collectors.toList());
        for (int i = 0; i < dataDictionaryList.size(); i++) {
            DataDictionary dictionary = dataDictionaryList.get(i);
            dictionary.setDisplayOrder(i + 1);
        }

        dataDictionaryRepository.saveOrUpdateBatch(dataDictionaryList);


        dataDictionaryRepository.edit(dataDictionary);
    }

    /**
     * 移除数据字典
     *
     * @param id
     */
    @Override
    public void removeDataDictionary(Long id) {
        DataDictionary byIdCheck = dataDictionaryRepository.getByIdCheck(id);
        if (byIdCheck.getIsSystem()!=null && byIdCheck.getIsSystem()) {
            throw new DataDictionaryTypeErrorException("系统数据字典不能删除");
        }

        dataDictionaryRepository.removeById(id);

        //重置排名
        DataDictionary t = new DataDictionary();
        t.setType(byIdCheck.getType());
        List<DataDictionary> dataDictionaryList = dataDictionaryRepository.getListByEntity(t);
        dataDictionaryList = dataDictionaryList.stream()
                .sorted(Comparator.comparingInt(DataDictionary::getDisplayOrder))
                .collect(Collectors.toList());
        for (int i = 0; i < dataDictionaryList.size(); i++) {
            DataDictionary dictionary = dataDictionaryList.get(i);
            dictionary.setDisplayOrder(i + 1);
        }
        dataDictionaryRepository.saveOrUpdateBatch(dataDictionaryList);
    }

    /**
     * 启动/禁用数据字典
     *
     * @param id
     */
    @Override
    public void enabledDataDictionary(Long id) {
        DataDictionary dataDictionary = dataDictionaryRepository.getByIdCheck(id);
        if (dataDictionary.getIsSystem()!=null && dataDictionary.getIsSystem()) {
            throw new DataDictionaryTypeErrorException("系统数据字典不能禁用");
        }
        dataDictionary.setIsDisable(!dataDictionary.getIsDisable());
        dataDictionaryRepository.edit(dataDictionary);
    }

    /**
     * 获取数据字典详情
     *
     * @param id
     * @return
     */
    @Override
    public GetDataDictionaryVo getDataDictionary(Long id) {
        DataDictionary dataDictionary = dataDictionaryRepository.getByIdCheck(id);
        GetDataDictionaryVo vo = new GetDataDictionaryVo();
        BeanUtils.copyProperties(dataDictionary, vo);
        return vo;
    }

    /**
     * 获取数据字典 列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<GetDataDictionaryListVo> getDataDictionaryList(GetDataDictionaryListParam param) {

        SelectDataDictionaryDto dto = new SelectDataDictionaryDto();
        BeanUtils.copyProperties(param, dto);
        Page<DataDictionary> page = dataDictionaryRepository.selectDataDictionary(dto);
        List<DataDictionary> dataDictionaryList = page.getRecords();

        List<Long> userIds = new ArrayList<>();
        List<Long> createIds = dataDictionaryList.stream()
                .map(DataDictionary::getCreator)
                .collect(Collectors.toList());

        List<Long> updateIds = dataDictionaryList.stream()
                .map(DataDictionary::getUpdater)
                .collect(Collectors.toList());


        userIds.addAll(createIds);
        userIds.addAll(updateIds);

        Map<Long, String> userNameMap = userRepository.getListByIds(updateIds)
                .stream()
                .collect(Collectors.toMap(User::getId, User::getName));


        List<GetDataDictionaryListVo> list = new ArrayList<>();
        for (DataDictionary dataDictionary : dataDictionaryList) {
            GetDataDictionaryListVo vo = new GetDataDictionaryListVo();
            BeanUtils.copyProperties(dataDictionary, vo);

            vo.setCreateName(userNameMap.get(dataDictionary.getCreator()));
            vo.setUpdateName(userNameMap.get(dataDictionary.getUpdater()));

            vo.setEnabled(!dataDictionary.getIsDisable());

            list.add(vo);
        }
        return new PageResult<>(list, page);

    }

    /**
     * 获取数据字典下拉列表
     *
     * @param param
     * @return
     */
    @Override
    public List<GetDataDictionaryDownListVo> getDataDictionaryDownList(GetDataDictionaryDownListParam param) {
        DataDictionary po = new DataDictionary();
        if (param != null) {
            BeanUtils.copyProperties(param, po);
        }

        DataDictionaryType t = new DataDictionaryType();
        BeanUtils.copyProperties(param, t);
        DataDictionaryType dataDictionaryType = dataDictionaryTypeRepository.getByEntity(t);
        if (dataDictionaryType == null) {
            throw new DataDictionaryTypeErrorException("");
        }

        po.setType(dataDictionaryType.getId());
        po.setIsDisable(Boolean.FALSE);
        List<DataDictionary> dataDictionaryList = dataDictionaryRepository.getListByEntity(po);

        List<GetDataDictionaryDownListVo> list = new ArrayList<>();
        for (DataDictionary dataDictionary : dataDictionaryList) {
            GetDataDictionaryDownListVo vo = new GetDataDictionaryDownListVo();
            BeanUtils.copyProperties(dataDictionary, vo);
            list.add(vo);
        }
        return list;
    }


}



